package com.android.launcher3;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.SystemClock;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;

/**
 * A ViewGroup that coordinated dragging across its dscendants
 */
public class DragLayer extends FrameLayout implements DragController {
	private DragController.DragListener mMenuListener;

	/** The bitmap that is currently being dragged */
	private Bitmap mDragBitmap = null;
	private DragScroller mDragMenuScroller;

	/** Where the drag originated */
	private DragSource mDragSource;

	private DropTarget mLastDropTarget;

	/** The data associated with the object being dragged */
	private Object mDragInfo;

	private final Paint mDimPaint;
	private final Paint mTrashPaint = new Paint();
	private InputMethodManager mInputMethodManager;
	private Paint mDragPaint;
	private final Paint mScrollPaint;

	/** Utility rectangle */
	private Rect mDragRect = new Rect();
	private final Rect mRect = new Rect();
	private final Vibrator mVibrator = new Vibrator();
	private RectF mDragRegion;
	private ScrollRunnable mScrollRunnable = new ScrollRunnable();
	private View mIgnoredDropTarget;
	private View mOriginator;
	private final int[] mDropCoordinates = new int[2];
	private DragListener mListener;
	private DragScroller mDragScroller;
	private DragAnimation[] mDragAnimation;
	private boolean mDragging = false;
	private boolean mEnteredRegion;
	private boolean mIsDragAnimation;
	private boolean mShouldDrop;
	private float mAnimationFrom;
	private float mAnimationTo;
	private float mLastMotionX;
	private float mLastMotionY;

	/** X offset from where we touched on the cell to its upper-left corner */
	private float mTouchOffsetX;

	/** Y offset from where we touched on the cell to its upper-left corner */
	private float mTouchOffsetY;

	private int mAnimationDuration;
	private int mAnimationState;
	private int mAnimationType;
	private int mBitmapOffsetX;
	private int mBitmapOffsetY;
	private int mScrollPaintColor;
	private int mScrollState = SCROLL_OUTSIDE_ZONE;
	private int mSrcColor1;
	private int mSrcColor2;
	private long mAnimationStartTime;
	private static final int SCROLL_DELAY = 600;
	private static final int SCROLL_ZONE = 50;

	// private static final int SCROLL_ZONE = 20;
	private static final int VIBRATE_DURATION = 35;
	private static final int ANIMATION_SCALE_UP_DURATION = 110;
	private static final boolean PROFILE_DRAWING_DURING_DRAG = false;

	// Number of pixels to add to the dragged item for scaling
	private static final int SCROLL_OUTSIDE_ZONE = 0;
	private static final int SCROLL_WAITING_IN_ZONE = 1;
	private static final int SCROLL_LEFT = 0;
	private static final int SCROLL_RIGHT = 1;
	private static final int ANIMATION_STATE_STARTING = 1;
	private static final int ANIMATION_STATE_RUNNING = 2;
	private static final int ANIMATION_STATE_DONE = 3;
	private static final int ANIMATION_TYPE_SCALE = 1;
	private static final String TAG = "DragLayer";
	private static final float DRAG_SCALE = 1.1F;
	private static final float DRAG_SCALE_WIDGET = 1.05F;

	/**
	 * Used to create a new DragLayer from XML.
	 * 
	 * @param context
	 *            The application's context.
	 * @param attrs
	 *            The attribtues set containing the Workspace's customization
	 *            values.
	 */
	public DragLayer(final Context context, final AttributeSet attrs) {
		super(context, attrs);

		LogUtils.d(TAG, "DragLayer");

		this.mAnimationState = ANIMATION_STATE_DONE;

		this.mDimPaint = new Paint();

		this.mScrollPaint = new Paint();

		final int srcColor = context.getResources().getColor(
				R.color.delete_color_filter);
		mTrashPaint.setColorFilter(new PorterDuffColorFilter(srcColor,
				PorterDuff.Mode.SRC_ATOP));

		// Make estimated paint area in gray
		int snagColor = context.getResources().getColor(
				R.color.snag_callout_color);

		Paint estimatedPaint = new Paint();
		estimatedPaint.setColor(snagColor);
		estimatedPaint.setStrokeWidth(3);
		estimatedPaint.setAntiAlias(true);

		this.mSrcColor1 = context.getResources().getColor(
				R.color.delete_color_filter);

		this.mSrcColor2 = context.getResources().getColor(
				R.color.uninstall_color_filter);

		this.mDimPaint.setColorFilter(new PorterDuffColorFilter(2130706432,
				PorterDuff.Mode.SRC_ATOP));

		this.mScrollPaintColor = context.getResources().getColor(
				R.color.scroll_color_filter);

		this.mScrollPaint.setColorFilter(new PorterDuffColorFilter(
				this.mScrollPaintColor, PorterDuff.Mode.SRC_ATOP));

		this.mDragAnimation = new DragAnimation[3];
	}

	/**
	 * 完整.
	 */
	public void cancelDrag() {
		LogUtils.d(TAG, "cancelDrag");
		removeCallbacks(this.mScrollRunnable);

		if (this.mShouldDrop) {
			drop(this.mLastMotionX, this.mLastMotionY);
			this.mShouldDrop = false;
		}

		if (this.mDragging) {
			this.mDragging = false;

			if (this.mDragBitmap != null) {
				this.mDragBitmap.recycle();
			}

			if ((this.mMenuListener == null) && (this.mOriginator != null)) {
				this.mOriginator.setVisibility(VISIBLE);
			}

			if (this.mListener != null) {
				this.mListener.onDragEnd();
			}
		}
	}

	@Override
	public boolean dispatchKeyEvent(final KeyEvent event) {
		LogUtils.d(TAG, "dispatchKeyEvent");

		return mDragging || super.dispatchKeyEvent(event);
	}

	@Override
	public boolean onInterceptTouchEvent(final MotionEvent ev) {
		LogUtils.d(TAG, "onInterceptTouchEvent");

		final int action = ev.getAction();

		final float x = ev.getX();
		final float y = ev.getY();

		switch (action) {
		case MotionEvent.ACTION_MOVE:
			break;

		case MotionEvent.ACTION_DOWN:
			// Remember location of down touch
			mLastMotionX = x;
			mLastMotionY = y;
			mLastDropTarget = null;

			break;

		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:

			if (mShouldDrop && drop(x, y)) {
				mShouldDrop = false;
			}

			endDrag();

			break;
		}

		LogUtils.d(TAG, "onInterceptTouchEvent=" + action + ", return="
				+ mDragging);

		return mDragging;
	}

	@Override
	public boolean onTouchEvent(final MotionEvent ev) {
		if (!mDragging) {
			LogUtils.d(TAG, "onTouchEvent=" + ev.getAction() + ", return false");

			return false;
		}

		final int action = ev.getAction();

		final float x = ev.getX();
		final float y = ev.getY();

		switch (action) {
		case MotionEvent.ACTION_DOWN: {
			// Remember where the motion event started
			mLastMotionX = x;
			mLastMotionY = y;

			if ((x < SCROLL_ZONE) || (x > getWidth() - SCROLL_ZONE)) {
				mScrollState = SCROLL_WAITING_IN_ZONE;
				postDelayed(mScrollRunnable, SCROLL_DELAY);
			} else {
				mScrollState = SCROLL_OUTSIDE_ZONE;
			}

			break;
		}

		case MotionEvent.ACTION_MOVE: {
			final int scrollX = mScrollX;
			final int scrollY = mScrollY;

			final float touchX = mTouchOffsetX;
			final float touchY = mTouchOffsetY;

			final int offsetX = mBitmapOffsetX;
			final int offsetY = mBitmapOffsetY;

			int left = (int) (scrollX + mLastMotionX - touchX - offsetX);
			int top = (int) (scrollY + mLastMotionY - touchY - offsetY);

			final Bitmap dragBitmap = mDragBitmap;
			final int width = dragBitmap.getWidth();
			final int height = dragBitmap.getHeight();

			final Rect rect = mRect;
			rect.set(left - 1, top - 1, left + width + 1, top + height + 1);

			mLastMotionX = x;
			mLastMotionY = y;

			left = (int) (scrollX + x - touchX - offsetX);
			top = (int) (scrollY + y - touchY - offsetY);

			// Invalidate current icon position
			rect.union(left - 1, top - 1, left + width + 1, top + height + 1);

			final int[] coordinates = mDropCoordinates;
			DropTarget dropTarget = findDropTarget((int) x, (int) y,
					coordinates);

			if (dropTarget != null) {
				// Log.e(TAG,"dropTarget "+ dropTarget.getClass().getName());

				// if(mLastDropTarget!=null){
				// Log.e(TAG,"mLastDropTarget "+
				// mLastDropTarget.getClass().getName());
				// }
				if (mLastDropTarget == dropTarget) {
					dropTarget.onDragOver(mDragSource, coordinates[0],
							coordinates[1], (int) mTouchOffsetX,
							(int) mTouchOffsetY, mDragInfo);
				} else {
					if (mLastDropTarget != null) {
						mLastDropTarget.onDragExit(mDragSource, coordinates[0],
								coordinates[1], (int) mTouchOffsetX,
								(int) mTouchOffsetY, mDragInfo);
					}

					dropTarget.onDragEnter(mDragSource, coordinates[0],
							coordinates[1], (int) mTouchOffsetX,
							(int) mTouchOffsetY, mDragInfo);
				}
			} else {
				if (mLastDropTarget != null) {
					mLastDropTarget.onDragExit(mDragSource, coordinates[0],
							coordinates[1], (int) mTouchOffsetX,
							(int) mTouchOffsetY, mDragInfo);
				}
			}

			invalidate(rect);

			mLastDropTarget = dropTarget;

			boolean inDragRegion = false;

			if (mDragRegion != null) {
				final RectF region = mDragRegion;
				final boolean inRegion = region.contains(ev.getRawX(),
						ev.getRawY());

				if (!mEnteredRegion && inRegion) {
					mDragPaint = mTrashPaint;
					mEnteredRegion = true;
					inDragRegion = true;
				} else if (mEnteredRegion && !inRegion) {
					this.mDragPaint = this.mDimPaint;
					mEnteredRegion = false;
				}
			}

			if (!inDragRegion && x < SCROLL_ZONE) {
				if (mScrollState == SCROLL_OUTSIDE_ZONE) {
					mScrollState = SCROLL_WAITING_IN_ZONE;
					mScrollRunnable.setDirection(SCROLL_LEFT);
					postDelayed(mScrollRunnable, SCROLL_DELAY);
					this.mDragPaint = this.mScrollPaint;
				}
			} else if (!inDragRegion && x > getWidth() - SCROLL_ZONE) {
				if (mScrollState == SCROLL_OUTSIDE_ZONE) {
					mScrollState = SCROLL_WAITING_IN_ZONE;
					mScrollRunnable.setDirection(SCROLL_RIGHT);
					postDelayed(mScrollRunnable, SCROLL_DELAY);
					this.mDragPaint = this.mScrollPaint;
				}
			} else {
				if (mScrollState == SCROLL_WAITING_IN_ZONE) {
					mScrollState = SCROLL_OUTSIDE_ZONE;
					mScrollRunnable.setDirection(SCROLL_RIGHT);
					removeCallbacks(mScrollRunnable);
				}
			}

			if (!this.mEnteredRegion) {
				this.mDragPaint = this.mDimPaint;
			}

			break;
		}

		case MotionEvent.ACTION_UP: {
			removeCallbacks(mScrollRunnable);

			if (mShouldDrop) {
				drop(x, y);
				mShouldDrop = false;
			}

			endDrag();

			break;
		}

		case MotionEvent.ACTION_CANCEL:
			endDrag();
		}

		LogUtils.d(TAG, "onTouchEvent=" + ev.getAction() + ", return true");

		return true;
	}

	public void removeDragListener(final DragListener l) {
		LogUtils.d(TAG, "removeDragListener");
		mListener = null;
	}

	public void setDragListener(final DragListener l) {
		LogUtils.d(TAG, "setDragListener");
		mListener = l;
	}

	public void setDragMenuListener(final DragController.DragListener l) {
		LogUtils.d(TAG, "setDragMenuListener");
		this.mMenuListener = l;
	}

	public void setDragMenuScoller(final DragScroller l) {
		LogUtils.d(TAG, "setDragMenuScoller");
		this.mDragMenuScroller = l;
	}

	public void setDragScoller(final DragScroller scroller) {
		LogUtils.d(TAG, "setDragScoller");
		mDragScroller = scroller;
	}

	public void setTrashPaint(final int paramInt) {
		LogUtils.d(TAG, "setTrashPaint");

		int i = 0;

		if (paramInt == 1) {
			i = this.mSrcColor2;
		} else {
			i = this.mSrcColor1;
		}

		PorterDuff.Mode localMode = PorterDuff.Mode.SRC_ATOP;
		PorterDuffColorFilter localPorterDuffColorFilter = new PorterDuffColorFilter(
				i, localMode);
		mTrashPaint.setColorFilter(localPorterDuffColorFilter);

		return;
	}

	/**
	 * 完整
	 */
	public void startAnimation(final View animationView, final float fromX,
			final float toX, final float fromY, final float toY,
			final float xOffset, final float yOffset, final int duration) {
		LogUtils.d(TAG, "startAnimation");

		int i = this.mDragAnimation.length;
		int j = 0;

		while (j < i) {
			if (this.mDragAnimation[j] == null) {
				this.mDragAnimation[j] = new DragAnimation(
						new DecelerateInterpolator());
				this.mDragAnimation[j].setAnimation(animationView, fromX, toX,
						fromY, toY, xOffset, yOffset, duration);
				this.mIsDragAnimation = true;
				// Log.e(TAG, "startAnimation before  invalidate");
				invalidate();

				// Log.e(TAG, "startAnimation after  invalidate");
			}

			j++;
		}
	}

	public void startDrag(final View v, final DragSource source,
			final Object dragInfo, final int dragAction) {
		LogUtils.d(TAG, "startDrag");

		if (PROFILE_DRAWING_DURING_DRAG) {
			android.os.Debug.startMethodTracing("Launcher");
		}

		// Hide soft keyboard, if visible
		if (mInputMethodManager == null) {
			mInputMethodManager = (InputMethodManager) getContext()
					.getSystemService(Context.INPUT_METHOD_SERVICE);
		}

		mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);

		if (mMenuListener != null) {
			mMenuListener.onDragStart(v, source, dragInfo, dragAction);
		} else {
			if (mListener != null) {
				mListener.onDragStart(v, source, dragInfo, dragAction);
			}
		}

		Rect r = mDragRect;
		r.set(v.getScrollX(), v.getScrollY(), 0, 0);

		offsetDescendantRectToMyCoords(v, r);
		mTouchOffsetX = mLastMotionX - r.left;
		mTouchOffsetY = mLastMotionY - r.top;

		if (dragAction == DragController.DRAG_ACTION_COPY_AND_ICON_CENTER) {
			View iconView = v.findViewById(R.id.icon);

			if (iconView != null) {
				this.mTouchOffsetX = iconView.getWidth() / 2;
				this.mTouchOffsetY = iconView.getHeight() / 2;
			}
		}

		v.clearFocus();
		v.setPressed(false);

		boolean willNotCache = v.willNotCacheDrawing();
		v.setWillNotCacheDrawing(false);

		// Reset the drawing cache background color to fully transparent
		// for the duration of this operation
		int color = v.getDrawingCacheBackgroundColor();
		v.setDrawingCacheBackgroundColor(0);

		if (color != 0) {
			v.destroyDrawingCache();
		}

		v.buildDrawingCache();

		Bitmap viewBitmap = v.getDrawingCache();
		int width = viewBitmap.getWidth();
		int height = viewBitmap.getHeight();

		// Matrix scale = new Matrix();
		// float scaleFactor = v.getWidth();
		// scaleFactor = (scaleFactor + DRAG_SCALE) / scaleFactor;
		// scale.setScale(scaleFactor, scaleFactor);
		Object localObject3 = v.getTag();

		if ((localObject3 != null)
				&& (localObject3 instanceof LauncherAppWidgetInfo)) {
			mAnimationTo = DRAG_SCALE_WIDGET;
		} else {
			mAnimationTo = DRAG_SCALE;
		}

		mAnimationFrom = 1.0f;
		mAnimationDuration = ANIMATION_SCALE_UP_DURATION;
		mAnimationState = ANIMATION_STATE_STARTING;
		mAnimationType = ANIMATION_TYPE_SCALE;

		mDragBitmap = Bitmap.createBitmap(viewBitmap);
		v.destroyDrawingCache();
		v.setWillNotCacheDrawing(willNotCache);
		v.setDrawingCacheBackgroundColor(color);

		final Bitmap dragBitmap = mDragBitmap;
		mBitmapOffsetX = (dragBitmap.getWidth() - width) / 2;
		mBitmapOffsetY = (dragBitmap.getHeight() - height) / 2;

		if (dragAction == DRAG_ACTION_MOVE) {
			if (mMenuListener != null) {
				v.setVisibility(INVISIBLE);
			} else {
				v.setVisibility(GONE);
			}
		}

		mDragPaint = this.mDimPaint;
		mDragging = true;
		mShouldDrop = true;
		mOriginator = v;
		mDragSource = source;
		mDragInfo = dragInfo;
		mVibrator.vibrate(VIBRATE_DURATION);
		mEnteredRegion = false;
		invalidate();
	}

	protected void dispatchDraw(final Canvas canvas) {
		LogUtils.d(TAG, "dispatchDraw-start");
		// Log.e(TAG,"dispatchDraw");
		super.dispatchDraw(canvas);

		if (mDragging && mDragBitmap != null) {
			if (mAnimationState == ANIMATION_STATE_STARTING) {
				mAnimationStartTime = SystemClock.uptimeMillis();
				mAnimationState = ANIMATION_STATE_RUNNING;
			}

			if (mAnimationState == ANIMATION_STATE_RUNNING) {
				float normalized = (float) (SystemClock.uptimeMillis() - mAnimationStartTime)
						/ mAnimationDuration;

				if (normalized >= 1.0f) {
					mAnimationState = ANIMATION_STATE_DONE;
				}

				normalized = Math.min(normalized, 1.0f);

				final float value = mAnimationFrom
						+ (mAnimationTo - mAnimationFrom) * normalized;

				switch (mAnimationType) {
				case ANIMATION_TYPE_SCALE:

					final Bitmap dragBitmap = mDragBitmap;
					canvas.save();
					canvas.translate(mScrollX + mLastMotionX - mTouchOffsetX
							- mBitmapOffsetX, mScrollY + mLastMotionY
							- mTouchOffsetY - mBitmapOffsetY);
					canvas.translate(
							(dragBitmap.getWidth() * (1.0f - value)) / 2,
							(dragBitmap.getHeight() * (1.0f - value)) / 2);
					canvas.scale(value, value);
					canvas.drawBitmap(dragBitmap, 0.0f, 0.0f, mDragPaint);
					canvas.restore();

					break;
				}
			} else {
				// Draw actual icon being dragged
				canvas.drawBitmap(mDragBitmap, mScrollX + mLastMotionX
						- mTouchOffsetX - mBitmapOffsetX, mScrollY
						+ mLastMotionY - mTouchOffsetY - mBitmapOffsetY,
						mDragPaint);
			}
		}

		if (this.mIsDragAnimation) {
			// Log.e(TAG,"dispatchDraw   DragAnimation");
			int i8 = 0;
			int i10 = 0;
			int i9 = this.mDragAnimation.length;

			while (i10 < i9) {
				DragAnimation localDragAnimation1 = this.mDragAnimation[i10];

				if (localDragAnimation1 != null) {
					int i11 = 0;

					if (this.mMenuListener != null) {
						View localView = localDragAnimation1.mAnimationView;
						i11 = this.mMenuListener
								.getDragAnimationXOffset(localView);
					}

					canvas.save();

					float f15 = localDragAnimation1.mXOffset;
					float f16 = i11;
					float f17 = f15 - f16;
					float f18 = f17;
					float f19 = 0.0F;
					canvas.translate(f18, f19);

					if (localDragAnimation1.draw(canvas)) {
						i8 = 1;
					} else {
						this.mDragAnimation[i10] = null;
					}

					canvas.restore();
				}

				i10++;
			}

			if (i8 != 0) {
				postInvalidate();
			} else {
				this.mIsDragAnimation = false;
			}
		}

		LogUtils.d(TAG, "dispatchDraw-end");
	}

	DropTarget findDropTarget(final int x, final int y,
			final int[] dropCoordinates) {
		LogUtils.d(TAG, "findDropTarget1");

		return findDropTarget(this, x, y, dropCoordinates);
	}

	View getOriginator() {
		return this.mOriginator;
	}

	/**
	 * Specifies the delete region.
	 * 
	 * @param region
	 *            The rectangle in screen coordinates of the delete region.
	 */
	void setDeleteRegion(final RectF region) {
		LogUtils.d(TAG, "setDeleteRegion");
		mDragRegion = region;
	}

	/**
	 * Specifies the view that must be ignored when looking for a drop target.
	 * 
	 * @param view
	 *            The view that will not be taken into account while looking for
	 *            a drop target.
	 */
	void setIgnoredDropTarget(final View view) {
		LogUtils.d(TAG, "setIgnoredDropTarget");
		mIgnoredDropTarget = view;
	}

	private boolean drop(final float x, final float y) {
		LogUtils.d(TAG, "drop");
		invalidate();

		final int[] coordinates = mDropCoordinates;
		DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);

		if (dropTarget != null) {
			dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
					(int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);

			if (dropTarget.acceptDrop(mDragSource, coordinates[0],
					coordinates[1], (int) mTouchOffsetX, (int) mTouchOffsetY,
					mDragInfo)) {
				dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1],
						(int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);
				mDragSource.onDropCompleted((View) dropTarget, true, null);

				return true;
			} else {
				mDragSource.onDropCompleted((View) dropTarget, false, null);

				return true;
			}
		}

		return false;
	}

	/**
	 * 完整.
	 */
	private void endDrag() {
		LogUtils.d(TAG, "endDrag");

		if (mDragging) {
			mDragging = false;

			if (mDragBitmap != null) {
				mDragBitmap.recycle();
			}

			if ((this.mMenuListener == null) && (this.mOriginator != null)) {
				this.mOriginator.setVisibility(VISIBLE);
			}

			if (mListener != null) {
				mListener.onDragEnd();
			}
		}
	}

	private DropTarget findDropTarget(final ViewGroup container, int x, int y,
			final int[] dropCoordinates) {
		LogUtils.d(TAG, "findDropTarget2");

		final Rect r = mDragRect;
		final int count = container.getChildCount();
		final int scrolledX = x + container.getScrollX();
		final int scrolledY = y + container.getScrollY();
		View ignoredDropTarget = mIgnoredDropTarget;

		if (this.mMenuListener != null) {
			ignoredDropTarget = null;
		}

		// 这样做是有问题的，为了赶时间，先就这样吧.
		if (this.mMenuListener != null) {
			for (int i = count - 1; i >= 0; i--) {
				final View child = container.getChildAt(i);

				if (child.getVisibility() == VISIBLE
						&& child instanceof MenuDrawer) {
					dropCoordinates[0] = x;
					dropCoordinates[1] = y;

					return (DropTarget) child;
				}
			}
		}

		for (int i = count - 1; i >= 0; i--) {
			final View child = container.getChildAt(i);

			if (child.getVisibility() == VISIBLE && child != ignoredDropTarget) {
				child.getHitRect(r);

				if (r.contains(scrolledX, scrolledY)) {
					DropTarget target = null;

					if (child instanceof ViewGroup) {
						x = scrolledX - child.getLeft();
						y = scrolledY - child.getTop();
						target = findDropTarget((ViewGroup) child, x, y,
								dropCoordinates);
					}

					if (target == null) {
						if (child instanceof DropTarget) {
							// Only consider this child if they will accept
							DropTarget childTarget = (DropTarget) child;

							if (childTarget.acceptDrop(mDragSource, x, y, 0, 0,
									mDragInfo)) {
								dropCoordinates[0] = x;
								dropCoordinates[1] = y;

								return (DropTarget) child;
							} else {
								return null;
							}
						}
					} else {
						return target;
					}
				}
			}
		}

		return null;
	}

	/**
	 * 完整
	 */
	private class ScrollRunnable implements Runnable {
		private int mDirection;

		/**
		 * Creates a new ScrollRunnable object.
		 */
		ScrollRunnable() {
		}

		public void run() {
			LogUtils.d(TAG, "ScrollRunnable-run");

			if (mDragScroller != null) {
				if (mDirection == SCROLL_LEFT) {
					mDragScroller.scrollLeft();

					if (mDragMenuScroller != null) {
						mDragMenuScroller.scrollLeft();
					}
				} else {
					mDragScroller.scrollRight();

					if (mDragMenuScroller != null) {
						mDragMenuScroller.scrollRight();
					}
				}

				mScrollState = SCROLL_OUTSIDE_ZONE;
			}
		}

		void setDirection(final int direction) {
			mDirection = direction;
		}
	}
}
